如同前一章節的import一樣,在Go的世界當中是不允許浪費任何資源的,因此只要變數進行了宣告就需要被使用,否則會出現variable declared and not used
的錯誤。
但有一例外,那就是變數名稱命名為 _
, 這表示你並不為該變數進行宣告。
首先我們一樣創建一個名為variable.go的文件,並在該文件進行解說與範例撰寫。
var Name Type = Expression
package main
import "fmt"
func main() {
var x int = 8
var a = 16
var b int
var _ = 10
fmt.Println(x, a, b)
}
運行後可得結果
8 16 0
型別Type
,會由表達式Expression
決定Type表達式Expression
,會由型別Type
來決定初始值為多少,常見的初始值有int
之於0
, bool
之於false
, string
之於" "
...等全域變數
只能透過var
。Name := Expression
宣告declare(:=)
跟 指派assign(=)
是不同的,一次宣告多個變數,若已宣告過的變數會自動變成assign效果
func main() {
var b int = 123
a, b := 100, 99
c, b := 0, 1
fmt.Println(a, b, c)
}
運行後可得結果
100 1 0
短宣告方便,常常使用來宣告初始化大量、生命週期短的區域變數(像是迴圈內的i, j變數)。
反之一般宣告則用來宣告長週期且型別明確的變數。
此外,如果看到下面類型的變數短宣告
result, err := ...
result, err都將會是區域變數
喔。
無法更動、無法刪除的變數,但用法跟變數var
一樣,const
後面可以接任何型別,
因為常數是無法更動的,因此常數名稱通常為全大寫
const PI = 3.14159
const HELLO = "Hello World"
iota
是希臘字符,在Golang中是關鍵字之一,用在宣告常數中,
效果為數字遞增,iota
本身數值從0開始,
主要讓工程師不用手動打遞增數像是0、1、2、3...。
const (
A = iota // 0
B // 1
_ // 2 佔位符也會被計算
C // 3
D = iota * 0.1 // 0.4 接續前面的 iota
E // 0.5
F // 0.6
G // 0.7
)
起始值也不一定要從0開始
const (
X = iota + 100 // 100
Y // 101
Z // 102
)
也常被拿來作 左移右移(Shift Bit) 運算
const (
b1 = 1 << iota // 1 右側被塞入0個bit (2^0 二的零次方)
b2 // 2 右側被塞入1個bit (2^1 二的一次方)
b3 // 4 右側被塞入2個bit
b4 // 8
b5 // 16
)
package main
import "fmt"
var a = "Hello!"
func main() {
b := 10
fmt.Println(&a, a, &b, b)
a, b := 100, 99
fmt.Println(&a, a, &b, b)
}
運算後可得結果
0x1157c80 Hello! 0xc000118000 10
0xc000118008 100 0xc000118000 99
只要有對相同變數名稱再次進行宣告,代表宣告新的變數名稱以及使用新的記憶體空間,
這也意味著原本的全域變數a
的地址被覆蓋掉了。
package main
import "fmt"
var i = 100
func main() {
fmt.Println(&i)
i = 200
fmt.Println(&i)
i := 150
fmt.Println(&i)
i, j := 250, 100
fmt.Println(&i, j)
}
fmt.Println(i, &i)
運算後可得結果
0x1149268
0x1149268
0xc0000ae008
0xc0000ae008 100
並非進行宣告或是短宣告後就會有全新的變數出現並挪用全新的記憶體空間,
Go會去尋找目前最小單位的區塊內是否已經有被宣告的變數,沒有的話才會宣告新的。
100
,並且i的地址為0x1149268
200
,這時候還是對同一個變數進行操作,因此地址依然為0x1149268
150
,由於該區域之前並未有其他i變數的存在,因此產生一個新的區域變數i,並賦予新的地址0xc0000ae008
,同時也意味著全域變數i的地址被覆蓋了250
即可,所以i的地址依然還是先前的0xc0000ae008
看到有var
會是全新的。
但看到:=
卻是不一定,短變數宣告可以伴隨著未宣告的變數一起出現。
package main
import "fmt"
var x = 123
func main() {
fmt.Println(&x)
var x = 123
fmt.Println(&x)
x, y := 123, 100
fmt.Println(&x, &y)
if true {
var x, y = 123, 100
// 可以換成短變數宣告。
fmt.Println(&x, &y)
}
fmt.Println(&x)
}
運行後可得結果
0x1149268
0xc00019a010
0xc00019a010 0xc00019a018
0xc00019a020 0xc00019a028
0xc00019a010
123
,並得到x地址為0x1149268
123
,並得到x地址為0xc00019a010
123
, 100
,但由於x變數在此區間先前以宣告過故依然使用地址0xc00019a010
,y地址則為0xc00019a018
123
, 100
,且由於x, y在該區域並未宣告過,因此此時x, y地址分別為 0xc00019a020
, 0xc00019a028
0xc00019a010
這章節只替大家帶來基本變數的宣告與使用,並透過記憶體位置的範例讓大家知道區域與全域變數在Go中的規則與變化,希望大家能避開這些坑。
下個章節則會透過不同型態的變數為各位解說。